Skip to content

feat: initial implementation#10

Draft
javier-godoy wants to merge 1 commit into
masterfrom
first-iteration
Draft

feat: initial implementation#10
javier-godoy wants to merge 1 commit into
masterfrom
first-iteration

Conversation

@javier-godoy
Copy link
Copy Markdown
Member

@javier-godoy javier-godoy commented May 13, 2026

Summary by CodeRabbit

  • New Features
    • Introduced EasyGrid: fluent typed column API, automatic column discovery, per-column/instance/global configuration, configurable renderer factories, and row actions UI.
  • Documentation
    • Added and reorganized docs with configuration-resolution rules, API reference, and usage examples.
  • Demos
    • Added multiple demo views showcasing auto-columns, type/number/date rendering, configuration hierarchy, typed and selective columns.
  • Tests
    • Added extensive unit and parameterized tests covering configuration layering, renderer factories, delegation and construction.
  • Chores
    • Updated project version/build metadata, README badge, .gitignore and demo styling.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 13, 2026

Walkthrough

Adds a new EasyGrid API and implementation: EasyGrid/EasyGridWrapper/EasyGridComposite, EasyColumn and IEasyGridColumn, multi-level ColumnConfiguration (global → instance → column) with renderer factories and renderer helpers; bean-property support, many demos/models/tests, docs, pom and .gitignore updates.

Changes

EasyGrid core, column configuration and renderers

Layer / File(s) Summary
ColumnConfiguration contract & text renderer
src/main/java/.../config/ColumnConfiguration.java, .../ColumnConfigurationImpl.java, .../ColumnConfigurationLink.java, .../ColumnConfigurationTextRenderer.java
Add sealed ColumnConfiguration<V> API; package-private ColumnConfigurationImpl with parent delegation; ColumnConfigurationLink read-through primary→fallback; ColumnConfigurationTextRenderer applies nullRepresentation and optional formatter.
Global & instance configuration maps and lifecycle
src/main/java/.../config/EasyGridConfigurationClassMap.java, .../GlobalEasyGridConfiguration.java, .../InstanceEasyGridConfiguration.java
Add synchronized class→configuration map with boxed-primitive handling; GlobalEasyGridConfiguration defaults, freeze/forType/resolve semantics; InstanceEasyGridConfiguration layers instance config over global via ColumnConfigurationLink.
RendererFactory and concrete renderer helpers
src/main/java/.../renderers/RendererFactory.java, .../LocalDateRenderers.java, .../LocalDateTimeRenderers.java, .../LocalTimeRenderers.java, .../NumberRenderers.java
Introduce RendererFactory<T,V> functional interface plus utility factories for LocalDate/LocalDateTime/LocalTime/Number with overloads for patterns, locales, suppliers and nullRepresentation.
Bean introspection & reflective helper
src/main/java/.../BeanPropertyDefinition.java, .../RuntimeReflectiveOperationException.java
Add BeanPropertyDefinition wrapping Vaadin PropertyDefinition and lazily exposing a JavaBeans PropertyDescriptor; add unchecked RuntimeReflectiveOperationException wrapper.

Grid API, wrapper and column façade

Layer / File(s) Summary
EasyGrid entry points & composite
src/main/java/.../EasyGrid.java, .../EasyGridWrapper.java, .../EasyGridComposite.java, .../IEasyGridComposite.java
Add EasyGrid<T> (concrete wrapper creating internal Grid<T>), EasyGridWrapper (bean-property-driven column creation, typed addColumn, ordering/hiding, typeConfiguration), EasyGridComposite and IEasyGridComposite exposing delegated Grid features.
EasyColumn façade & fluent API
src/main/java/.../EasyColumn.java, .../IEasyGridColumn.java
Add EasyColumn<T,V> attaching a ColumnConfiguration<V> to a Grid.Column<T> with fluent setters (setNullRepresentation, setFormatter, setRendererFactory, as(...), setTextAlign) and renderer refresh; add IEasyGridColumn sealed interface with many default fluent delegation methods to underlying Grid.Column.

Demos, models, services

Layer / File(s) Summary
Demo models and fixtures
src/test/java/.../model/Person.java, .../Address.java, .../NumberSample.java, src/test/java/.../data/PersonData.java, src/test/java/.../service/PersonService.java
Add demo/test models (Person, Address, NumberSample), data generator PersonData, and simple PersonService helpers used by demos/tests.
Demo views and registration
src/test/java/.../AutoColumnsDemo.java, .../SelectiveColumnsDemo.java, .../ColumnConfigurationDemo.java, .../ConfigurationHierarchyDemo.java, .../TypeRenderingDemo.java, .../TypedColumnDemo.java, .../NumberRenderingDemo.java, .../EasyGridDemoView.java
Add multiple routed demo views exercising auto/explicit/typed columns and configuration hierarchy; remove obsolete EasyGridDemo; register demos and add demo CSS import.
Demo CSS & resources
src/test/resources/.../easy-grid-demo-styles.css, .../shared-styles.css
Add demo CSS rule and update/add license headers in test resources.

Tests, harness and utilities

Layer / File(s) Summary
Delegation test harness & helpers
src/test/java/.../test/DelegationTest.java, .../EasyColumnTestHelper.java, .../GridColumnMethodLister.java
Add reflective parameterized DelegationTest base class, EasyColumnTestHelper for reflective construction/mocks, and a GridColumnMethodLister utility.
Parameterized delegation & behavior tests
src/test/java/.../test/ColumnConfigurationImplParentDelegationTest.java, .../ColumnConfigurationLinkDelegationTest.java, .../EasyColumnToConfigurationDelegationTest.java, .../EasyColumnToGridColumnDelegationTest.java
Add parameterized tests verifying delegation semantics for ColumnConfigurationImpl parent-delegation, ColumnConfigurationLink primary→fallback behavior, EasyColumnColumnConfiguration setter delegation, and EasyColumnGrid.Column setter delegation.
Global config & renderer tests; construction & serialization
src/test/java/.../test/GlobalEasyGridConfigurationTest.java, .../GlobalEasyGridConfigurationFreezeTest.java, .../GlobalRendererFactoryTest.java, .../EasyGridConstructionTest.java, .../SerializationTest.java
Add tests covering global config resolution (including primitives), freeze semantics, default renderer factories, EasyGrid construction behaviors, and serialization of EasyGrid<Person> (with UI locale context). Remove old integration test ViewIT.

Docs, build, metadata

Layer / File(s) Summary
Specifications and feature docs
SPECIFICATIONS.md, CONFIGURATION_RESOLUTION.md, FEATURE_ROW_ACTIONS.md, README.md
Rewrite SPECIFICATIONS.md for the new API and type-resolution; add CONFIGURATION_RESOLUTION.md documenting scope-first resolution and current implementation; add FEATURE_ROW_ACTIONS.md documenting row-actions API; update README badge URL casing.
Build files and ignores
pom.xml, .gitignore
Bump project/version/properties, add jakarta.servlet-api:6.0.0 (provided), add test deps (Mockito, Vaadin testbench-unit, Vaadin, JavaFaker), change profile javadoc URL and demo-processor, and update .gitignore to ignore /src/main/dev-bundle and /.claude/settings.local.json.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch first-iteration

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 12

🧹 Nitpick comments (5)
src/test/java/com/flowingcode/vaadin/addons/easygrid/model/Person.java (1)

49-52: ⚡ Quick win

Reorganize field declarations before methods.

The active field (line 52) is declared after the getAppointmentTime() method. Java convention is to group all field declarations together before methods. This makes the class structure clearer and easier to navigate.

♻️ Suggested reorganization
   private String phoneNumber;
   private LocalDate birthDate;
   private LocalDateTime appointmentDateTime;
   private boolean subscriber;
+  private boolean active;

   public LocalTime getAppointmentTime() {
     return appointmentDateTime != null ? appointmentDateTime.toLocalTime() : null;
   }
-  private boolean active;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/test/java/com/flowingcode/vaadin/addons/easygrid/model/Person.java`
around lines 49 - 52, The field declaration for active is placed after the
method getAppointmentTime() in class Person; move the private boolean active;
declaration up into the block with the other field declarations (i.e. group all
fields together at the top of the class) so that all fields are declared before
any methods, preserving existing modifiers and order of other fields.
src/main/java/com/flowingcode/vaadin/addons/easygrid/renderers/RendererFactory.java (1)

33-33: ⚡ Quick win

Consider adding @FunctionalInterface annotation.

While the interface correctly extends SerializableFunction and will be treated as a functional interface by the compiler, explicitly annotating it with @FunctionalInterface is a Java best practice that makes the intent clear and enables compile-time verification.

📝 Suggested addition
 /**
  * A named functional interface that creates a {`@link` Renderer} for a grid column given a
  * {`@link` com.vaadin.flow.function.ValueProvider}.
  *
  * `@param` <T> the grid bean type
  * `@param` <V> the column value type
  */
+@FunctionalInterface
 public interface RendererFactory<T, V> extends SerializableFunction<ValueProvider<T, V>, Renderer<T>> {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@src/main/java/com/flowingcode/vaadin/addons/easygrid/renderers/RendererFactory.java`
at line 33, Add the `@FunctionalInterface` annotation to the RendererFactory
interface declaration (RendererFactory<T, V> extends
SerializableFunction<ValueProvider<T, V>, Renderer<T>>) so the compiler enforces
the functional-interface contract and the intent is explicit; simply annotate
the interface line with `@FunctionalInterface` and keep the existing generic
signature unchanged.
src/main/java/com/flowingcode/vaadin/addons/easygrid/BeanPropertyDefinition.java (1)

74-80: ⚡ Quick win

Avoid relying on Vaadin internal API for descriptor lookup.

Line 77 calls com.vaadin.flow.internal.BeanUtil, which is explicitly marked "For internal use only. May be renamed or removed in a future release." Use the public JavaBeans API instead: new PropertyDescriptor(propertyName, beanType) directly instantiates the descriptor without requiring Vaadin internals.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@src/main/java/com/flowingcode/vaadin/addons/easygrid/BeanPropertyDefinition.java`
around lines 74 - 80, The method getPropertyDescriptor in BeanPropertyDefinition
currently uses the Vaadin internal BeanUtil (BeanUtil.getPropertyDescriptor)
which is unsupported; replace that call with the public JavaBeans API by
creating a new PropertyDescriptor(propertyName, beanType) and keep existing
exception handling (catch IntrospectionException and rethrow as
RuntimeReflectiveOperationException) so behavior remains the same; update
imports to use java.beans.PropertyDescriptor and remove dependency on
com.vaadin.flow.internal.BeanUtil.
src/test/java/com/flowingcode/vaadin/addons/easygrid/test/GlobalRendererFactoryTest.java (1)

36-41: 💤 Low value

Consider type-safe renderer factory invocation.

The explicit <Object> type parameter combined with the cast to LocalDate bypasses compile-time type safety. While this works in the test context, a more type-safe approach would preserve the resolved type.

♻️ Alternative approach
-    var config = new InstanceEasyGridConfiguration().resolve(LocalDate.class);
-    var renderer = config.<Object>getRendererFactory().apply(v -> (LocalDate) v);
+    var config = new InstanceEasyGridConfiguration().resolve(LocalDate.class);
+    var renderer = config.getRendererFactory().apply(v -> v);

The same pattern applies to the other test methods below.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@src/test/java/com/flowingcode/vaadin/addons/easygrid/test/GlobalRendererFactoryTest.java`
around lines 36 - 41, The test globalLocalDateRendererFactoryIsApplied uses an
unchecked cast via config.<Object>getRendererFactory().apply(v -> (LocalDate)
v), which bypasses compile-time type safety; change the generic invocation to
the resolved type (use config.<LocalDate>getRendererFactory()) and provide a
type-safe lambda (e.g., v -> v) so no cast is needed; update the same pattern in
the other test methods that call
InstanceEasyGridConfiguration.getRendererFactory to preserve type safety and
avoid raw/unchecked casts, and verify the result is still
instanceOf(LocalDateRenderer.class).
src/main/java/com/flowingcode/vaadin/addons/easygrid/EasyGridWrapper.java (1)

248-256: 💤 Low value

Consider excluding void.class from the primitive sortability check.

Line 252 uses type.isPrimitive() to determine sortability, but void.class.isPrimitive() returns true even though void values cannot be compared. While this is unlikely to occur in practice (since column value providers wouldn't return void), adding an explicit check would make the code more defensive.

🛡️ Optional defensive check
-    if (Comparable.class.isAssignableFrom(type) || type.isPrimitive()) {
+    if (Comparable.class.isAssignableFrom(type) || (type.isPrimitive() && type != void.class)) {
       column.setComparator((ValueProvider) getter);
     }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/java/com/flowingcode/vaadin/addons/easygrid/EasyGridWrapper.java`
around lines 248 - 256, In createEasyColumn(Class<V> type, ValueProvider<T, V>
getter) the sortability check currently treats all primitives as sortable; make
it defensive by excluding void.class from the primitive branch so void values
aren't considered comparable — change the condition that sets
column.setComparator(...) (referencing createEasyColumn, type.isPrimitive(), and
Comparable.class.isAssignableFrom) to only treat primitives as sortable when
type != void.class.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@CONFIGURATION_RESOLUTION.md`:
- Around line 13-20: Several fenced code blocks in CONFIGURATION_RESOLUTION.md
are unlabeled and trigger MD040; update each triple-backtick fence that contains
sequences like "I·Foo → I·Entity → G·Foo → G·Entity → Default", "I·Foo → G·Foo →
I·Entity → G·Entity → Default", "per-column → I·Foo → I·Entity → I·Object →
G·Foo → G·Entity → G·Object → Default", "I·Foo(impl) → I·Entity(impl) →
I·Object(impl)", "G·Foo(impl) → G·Entity(impl) → G·Object(impl)", and
"ColumnConfigurationLink(primary = I·Foo chain, fallback = G·Foo chain)" to use
a language identifier (e.g., text) after the opening ``` so the fences read
```text and satisfy markdown linting.

In `@FEATURE_ROW_ACTIONS.md`:
- Around line 51-54: The example uses easyGrid.addRowAction but refreshes using
grid.getDataProvider().refreshAll(), causing a variable-name mismatch; update
the refresh call to use easyGrid.getDataProvider().refreshAll() (or consistently
rename the grid variable so addRowAction, the deletion call
personService.delete(person), and the subsequent refresh all reference the same
grid instance) so the snippet is internally consistent.

In `@SPECIFICATIONS.md`:
- Around line 184-189: The fenced code block containing the snippet that starts
with "Column·Foo" is missing a language tag; update the opening fence from ```
to ```text so the block is explicitly marked (e.g., change the fence before
"Column·Foo" to "```text") to satisfy MD040; keep the block contents unchanged
and leave the closing fence as ``` to complete the fix.

In
`@src/main/java/com/flowingcode/vaadin/addons/easygrid/BeanPropertyDefinition.java`:
- Around line 66-69: The catch block in BeanPropertyDefinition that currently
catches NoSuchElementException | IllegalArgumentException and rethrows a new
IllegalArgumentException for "Can't resolve property name '" + propertyName + "'
from '" + propertySet + "'" must preserve the original exception as the cause;
modify the throw in that catch to pass the caught exception (e) as the cause
when constructing the new IllegalArgumentException so the root cause is retained
in stack traces and logs, keeping the same message but using the constructor
IllegalArgumentException(String, Throwable) (or equivalent) referencing
propertyName and propertySet.

In
`@src/main/java/com/flowingcode/vaadin/addons/easygrid/config/ColumnConfigurationLink.java`:
- Around line 38-41: The class ColumnConfigurationLink currently allows a null
primary which causes setters that call primary.* to NPE at runtime; ensure
primary is non-null by adding an explicit null check (e.g.
Objects.requireNonNull(primary, "primary must not be null")) in the
ColumnConfigurationLink constructor(s) and update any factory methods to enforce
the same, and keep fallback nullable as before; this guarantees setters that
call primary.* (and any methods in ColumnConfigurationLink that assume primary
!= null) are safe.

In
`@src/main/java/com/flowingcode/vaadin/addons/easygrid/config/GlobalEasyGridConfiguration.java`:
- Around line 70-87: There is a race between freeze() and forType(Class<V>)
because the check of the static boolean frozen and the call to
map.getOrCreate(type) are not atomic; fix it by synchronizing access: make
freeze() and forType(...) coordinate on the same lock (e.g., synchronize on
GlobalEasyGridConfiguration.class or add a private static final Object LOCK) and
perform the frozen check and the call to map.getOrCreate(type) inside the same
synchronized block (or use a ReentrantReadWriteLock with write lock in freeze()
and read lock in forType()) so no concurrent thread can create a registration
after freeze() completes.

In
`@src/test/java/com/flowingcode/vaadin/addons/easygrid/ColumnConfigurationDemo.java`:
- Around line 77-79: The Boolean formatter on
grid.getColumn("subscriber").as(Boolean.class).setFormatter(...) is not
null-safe; update the formatter to guard against null (e.g., treat null as false
or return an explicit placeholder like "Unknown") before dereferencing so it
never throws NPE. Modify the lambda passed to setFormatter on the subscriber
column to first check v for null and then return "Subscribed" or "Not
Subscribed" (or your chosen null placeholder) accordingly.

In
`@src/test/java/com/flowingcode/vaadin/addons/easygrid/model/NumberSample.java`:
- Around line 36-43: The constructor NumberSample(BigDecimal) currently converts
bigDecimal to smaller integer types without overflow checks (fields: bigDecimal,
bigInteger, integer, intValue, longValue, doubleValue), causing silent overflow
for values like 1234567890123.456; either: 1) update the conversions to use
exact checks (use bigInteger = value.toBigInteger(); integer =
bigInteger.intValueExact(); intValue = integer; longValue =
bigInteger.longValueExact();) so an ArithmeticException is thrown on overflow,
or 2) change the demo input in NumberRenderingDemo to a smaller BigDecimal that
fits int/long ranges, or add a comment documenting that overflow is intentional
— pick one approach and apply it consistently to NumberSample's constructor and
the demo.

In
`@src/test/java/com/flowingcode/vaadin/addons/easygrid/service/PersonService.java`:
- Around line 30-37: The fetch method should validate and clamp pagination
bounds before calling personData.getPersons().subList: ensure offset and limit
are non-negative (treat negative as 0), if limit == 0 return empty list
immediately, clamp offset to be at most size (if offset >= size return empty
list), compute end = min(offset + limit, size) and ensure end >= offset before
calling subList; update the fetch(...) implementation to perform these guards
using the existing fetch method and personData.getPersons() references.

In
`@src/test/java/com/flowingcode/vaadin/addons/easygrid/test/DelegationTest.java`:
- Around line 126-133: The buildArg method in DelegationTest only handles
boolean and int primitives and will fail for other primitive parameter types;
update buildArg to cover all primitive types (long, short, byte, char, float,
double) by adding branches like long.class -> Long.valueOf(0L), double.class ->
Double.valueOf(0.0), float.class -> Float.valueOf(0.0f), short.class ->
Short.valueOf((short)0), byte.class -> Byte.valueOf((byte)0), char.class ->
Character.valueOf('\0') while keeping the existing boolean and int branches, and
preserve the existing array and Mockito.mock(type) fallback so arrays and
reference types still behave as before.
- Around line 188-190: The isChainable method is using the wrong variable and a
brittle name-based heuristic; change it to inspect the method's return type
using the targetMethod parameter and treat methods returning void as
non-chainable (e.g., return !targetMethod.getReturnType().equals(Void.TYPE));
update references from method to targetMethod in isChainable to fix the variable
mismatch and derive chainability from the return type instead.

In `@src/test/java/com/flowingcode/vaadin/addons/easygrid/TypedColumnDemo.java`:
- Around line 68-73: The computed-days-until-birthday code in
TypedColumnDemo.java can throw for Feb 29 births when calling
p.getBirthDate().withYear(today.getYear()); fix by computing the birthday via
MonthDay (e.g., MonthDay birthMd = MonthDay.from(p.getBirthDate())), then create
birthday = birthMd.isValidYear(today.getYear()) ?
birthMd.atYear(today.getYear()) : MonthDay.of(2,28).atYear(today.getYear()) (or
another chosen fallback) so Feb 29 is handled safely, then keep the existing
logic that pushes the birthday to next year and returns today.until(birthday,
ChronoUnit.DAYS).

---

Nitpick comments:
In
`@src/main/java/com/flowingcode/vaadin/addons/easygrid/BeanPropertyDefinition.java`:
- Around line 74-80: The method getPropertyDescriptor in BeanPropertyDefinition
currently uses the Vaadin internal BeanUtil (BeanUtil.getPropertyDescriptor)
which is unsupported; replace that call with the public JavaBeans API by
creating a new PropertyDescriptor(propertyName, beanType) and keep existing
exception handling (catch IntrospectionException and rethrow as
RuntimeReflectiveOperationException) so behavior remains the same; update
imports to use java.beans.PropertyDescriptor and remove dependency on
com.vaadin.flow.internal.BeanUtil.

In `@src/main/java/com/flowingcode/vaadin/addons/easygrid/EasyGridWrapper.java`:
- Around line 248-256: In createEasyColumn(Class<V> type, ValueProvider<T, V>
getter) the sortability check currently treats all primitives as sortable; make
it defensive by excluding void.class from the primitive branch so void values
aren't considered comparable — change the condition that sets
column.setComparator(...) (referencing createEasyColumn, type.isPrimitive(), and
Comparable.class.isAssignableFrom) to only treat primitives as sortable when
type != void.class.

In
`@src/main/java/com/flowingcode/vaadin/addons/easygrid/renderers/RendererFactory.java`:
- Line 33: Add the `@FunctionalInterface` annotation to the RendererFactory
interface declaration (RendererFactory<T, V> extends
SerializableFunction<ValueProvider<T, V>, Renderer<T>>) so the compiler enforces
the functional-interface contract and the intent is explicit; simply annotate
the interface line with `@FunctionalInterface` and keep the existing generic
signature unchanged.

In `@src/test/java/com/flowingcode/vaadin/addons/easygrid/model/Person.java`:
- Around line 49-52: The field declaration for active is placed after the method
getAppointmentTime() in class Person; move the private boolean active;
declaration up into the block with the other field declarations (i.e. group all
fields together at the top of the class) so that all fields are declared before
any methods, preserving existing modifiers and order of other fields.

In
`@src/test/java/com/flowingcode/vaadin/addons/easygrid/test/GlobalRendererFactoryTest.java`:
- Around line 36-41: The test globalLocalDateRendererFactoryIsApplied uses an
unchecked cast via config.<Object>getRendererFactory().apply(v -> (LocalDate)
v), which bypasses compile-time type safety; change the generic invocation to
the resolved type (use config.<LocalDate>getRendererFactory()) and provide a
type-safe lambda (e.g., v -> v) so no cast is needed; update the same pattern in
the other test methods that call
InstanceEasyGridConfiguration.getRendererFactory to preserve type safety and
avoid raw/unchecked casts, and verify the result is still
instanceOf(LocalDateRenderer.class).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: a325efc3-43a7-4ca9-b6f0-4641a95438d9

📥 Commits

Reviewing files that changed from the base of the PR and between f30af8c and 219354b.

📒 Files selected for processing (56)
  • .gitignore
  • CONFIGURATION_RESOLUTION.md
  • FEATURE_ROW_ACTIONS.md
  • README.md
  • SPECIFICATIONS.md
  • pom.xml
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/BeanPropertyDefinition.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/EasyColumn.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/EasyGrid.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/EasyGridComposite.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/EasyGridWrapper.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/IEasyGridColumn.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/IEasyGridComposite.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/RuntimeReflectiveOperationException.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/config/ColumnConfiguration.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/config/ColumnConfigurationImpl.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/config/ColumnConfigurationLink.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/config/ColumnConfigurationTextRenderer.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/config/EasyGridConfigurationClassMap.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/config/GlobalEasyGridConfiguration.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/config/InstanceEasyGridConfiguration.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/renderers/LocalDateRenderers.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/renderers/LocalDateTimeRenderers.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/renderers/LocalTimeRenderers.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/renderers/NumberRenderers.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/renderers/RendererFactory.java
  • src/test/java/com/flowingcode/vaadin/addons/DemoLayout.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/AutoColumnsDemo.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/ColumnConfigurationDemo.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/ConfigurationHierarchyDemo.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/DemoView.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/EasyGridDemo.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/EasyGridDemoView.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/GridColumnMethodLister.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/NumberRenderingDemo.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/SelectiveColumnsDemo.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/TypeRenderingDemo.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/TypedColumnDemo.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/data/PersonData.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/it/AbstractViewTest.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/it/ViewIT.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/model/Address.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/model/NumberSample.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/model/Person.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/service/PersonService.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/test/ColumnConfigurationImplParentDelegationTest.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/test/ColumnConfigurationLinkDelegationTest.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/test/DelegationTest.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/test/EasyColumnTestHelper.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/test/EasyColumnToConfigurationDelegationTest.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/test/EasyColumnToGridColumnDelegationTest.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/test/GlobalEasyGridConfigurationTest.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/test/GlobalRendererFactoryTest.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/test/SerializationTest.java
  • src/test/resources/META-INF/frontend/styles/easy-grid-demo-styles.css
  • src/test/resources/META-INF/frontend/styles/shared-styles.css
💤 Files with no reviewable changes (2)
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/EasyGridDemo.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/it/ViewIT.java

Comment on lines +13 to +20
```
I·Foo → I·Entity → G·Foo → G·Entity → Default
```

**Type-first** exhausts all Foo-specific settings before looking at Entity:
```
I·Foo → G·Foo → I·Entity → G·Entity → Default
```
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot May 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Add language identifiers to fenced code blocks.

Line 13, Line 18, Line 78, Line 86, Line 92, and Line 98 use unlabeled fences, which triggers MD040 and can fail markdown lint gates.

Suggested fix
-```
+```text
 I·Foo → I·Entity → G·Foo → G·Entity → Default

- +text
I·Foo → G·Foo → I·Entity → G·Entity → Default


-```
+```text
per-column → I·Foo → I·Entity → I·Object → G·Foo → G·Entity → G·Object → Default

- +text
I·Foo(impl) → I·Entity(impl) → I·Object(impl)


-```
+```text
G·Foo(impl) → G·Entity(impl) → G·Object(impl)

- +text
ColumnConfigurationLink(primary = I·Foo chain, fallback = G·Foo chain)

Also applies to: 78-100

🧰 Tools
🪛 markdownlint-cli2 (0.22.1)

[warning] 13-13: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


[warning] 18-18: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@CONFIGURATION_RESOLUTION.md` around lines 13 - 20, Several fenced code blocks
in CONFIGURATION_RESOLUTION.md are unlabeled and trigger MD040; update each
triple-backtick fence that contains sequences like "I·Foo → I·Entity → G·Foo →
G·Entity → Default", "I·Foo → G·Foo → I·Entity → G·Entity → Default",
"per-column → I·Foo → I·Entity → I·Object → G·Foo → G·Entity → G·Object →
Default", "I·Foo(impl) → I·Entity(impl) → I·Object(impl)", "G·Foo(impl) →
G·Entity(impl) → G·Object(impl)", and "ColumnConfigurationLink(primary = I·Foo
chain, fallback = G·Foo chain)" to use a language identifier (e.g., text) after
the opening ``` so the fences read ```text and satisfy markdown linting.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Defer to reviewers' judgment. This file is intended for AI consumption.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@javier-godoy, understood — I'll dismiss this concern. Since CONFIGURATION_RESOLUTION.md is intended for AI consumption rather than human readers or standard documentation pipelines, markdown lint compliance is not a meaningful concern here.


✏️ Learnings added
Learnt from: javier-godoy
Repo: FlowingCode/EasyGridAddon PR: 10
File: CONFIGURATION_RESOLUTION.md:13-20
Timestamp: 2026-05-14T12:05:24.375Z
Learning: The file `CONFIGURATION_RESOLUTION.md` in the `FlowingCode/EasyGridAddon` repository is intended for AI consumption, not for human readers or standard documentation pipelines. Markdown style/lint issues (e.g., MD040 unlabeled fenced code blocks) should not be flagged in this file during code reviews.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

Comment thread FEATURE_ROW_ACTIONS.md
Comment thread SPECIFICATIONS.md
Comment thread src/test/java/com/flowingcode/vaadin/addons/easygrid/TypedColumnDemo.java Outdated
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (1)
src/test/java/com/flowingcode/vaadin/addons/easygrid/TypedColumnDemo.java (1)

67-73: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Handle leap-day birthdays safely in computed column logic.

Line 69/Line 72 can throw at runtime for Feb 29 birthdays in non-leap years due to withYear(...), which can break rendering for those rows.

Suggested fix
 import java.time.LocalDate;
+import java.time.MonthDay;
 import java.time.temporal.ChronoUnit;
@@
     grid.addColumn(Integer.class, p -> {
       LocalDate today = LocalDate.now();
-      LocalDate birthday = p.getBirthDate().withYear(today.getYear());
+      MonthDay birthMd = MonthDay.from(p.getBirthDate());
+      LocalDate birthday = birthMd.atYear(today.getYear());
 
       if (birthday.isBefore(today)) {
-        birthday = p.getBirthDate().withYear(today.getYear() + 1);
+        birthday = birthMd.atYear(today.getYear() + 1);
       }
 
       return (int) ChronoUnit.DAYS.between(today, birthday);
     }).setHeader("Days Until Birthday");
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/test/java/com/flowingcode/vaadin/addons/easygrid/TypedColumnDemo.java`
around lines 67 - 73, The computed-birthday logic in grid.addColumn (the lambda
using p.getBirthDate() and withYear(...)) can throw for Feb 29 birthdays in
non-leap years; update the code that computes birthday to choose a valid day for
the target year instead of blindly calling withYear. Concretely, compute
targetYear = today.getYear() (and targetYear+1 where used), then build birthday
using LocalDate.of(targetYear, birthDate.getMonthValue(),
Math.min(birthDate.getDayOfMonth(), Year.of(targetYear).length())) (or wrap
withYear in a try/catch and fallback to the last valid day of the month) so Feb
29s are mapped safely to Feb 28 in non-leap years before the before/after
comparisons.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Duplicate comments:
In `@src/test/java/com/flowingcode/vaadin/addons/easygrid/TypedColumnDemo.java`:
- Around line 67-73: The computed-birthday logic in grid.addColumn (the lambda
using p.getBirthDate() and withYear(...)) can throw for Feb 29 birthdays in
non-leap years; update the code that computes birthday to choose a valid day for
the target year instead of blindly calling withYear. Concretely, compute
targetYear = today.getYear() (and targetYear+1 where used), then build birthday
using LocalDate.of(targetYear, birthDate.getMonthValue(),
Math.min(birthDate.getDayOfMonth(), Year.of(targetYear).length())) (or wrap
withYear in a try/catch and fallback to the last valid day of the month) so Feb
29s are mapped safely to Feb 28 in non-leap years before the before/after
comparisons.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 1b032e9f-8d3a-46cd-983c-6557e27a2096

📥 Commits

Reviewing files that changed from the base of the PR and between 12bc9bb and 031a694.

📒 Files selected for processing (11)
  • pom.xml
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/EasyColumn.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/EasyGridComposite.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/EasyGridWrapper.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/IEasyGridColumn.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/IEasyGridComposite.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/config/GlobalEasyGridConfiguration.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/TypedColumnDemo.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/model/NumberSample.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/service/PersonService.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/test/DelegationTest.java
🚧 Files skipped from review as they are similar to previous changes (10)
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/model/NumberSample.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/service/PersonService.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/EasyGridComposite.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/config/GlobalEasyGridConfiguration.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/IEasyGridColumn.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/EasyGridWrapper.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/IEasyGridComposite.java
  • pom.xml
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/EasyColumn.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/test/DelegationTest.java

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/test/java/com/flowingcode/vaadin/addons/easygrid/test/GlobalEasyGridConfigurationFreezeTest.java (1)

51-54: 💤 Low value

Consider clarifying the test name.

The test name suggests it verifies that an entry is created, but the implementation only checks that resolve() returns non-null without verifying whether a new entry was actually created. Since LocalDate is pre-registered (per the comment on line 71), this test may be verifying retrieval rather than creation. Consider renaming to something like resolveBeforeFreezeReturnsNonNull or adding assertions to explicitly verify creation behavior if that's the intent.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@src/test/java/com/flowingcode/vaadin/addons/easygrid/test/GlobalEasyGridConfigurationFreezeTest.java`
around lines 51 - 54, The test name resolveBeforeFreezeCreatesEntry is
misleading because it only asserts
GlobalEasyGridConfiguration.resolve(LocalDate.class) != null; either rename the
test to resolveBeforeFreezeReturnsNonNull (or similar) to reflect its behavior,
or modify the test to explicitly verify creation (e.g., assert absence in the
registry before calling resolve and presence after) by using the registry
accessors used elsewhere in GlobalEasyGridConfiguration; update the method name
and any references accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@src/test/java/com/flowingcode/vaadin/addons/easygrid/test/EasyGridConstructionTest.java`:
- Around line 55-59: The test currently uses hasItems(...) which allows extra
unexpected columns; update the assertion in EasyGridConstructionTest so the
collected keys (from grid.getWrappedGrid().getColumns() -> keys) are asserted
for exact content/size — e.g., replace the hasItems assertion with an
exact-match assertion (such as assertThat(keys, contains(...)) or assertEquals
on a List of expected keys) to ensure no extra columns are present.

---

Nitpick comments:
In
`@src/test/java/com/flowingcode/vaadin/addons/easygrid/test/GlobalEasyGridConfigurationFreezeTest.java`:
- Around line 51-54: The test name resolveBeforeFreezeCreatesEntry is misleading
because it only asserts GlobalEasyGridConfiguration.resolve(LocalDate.class) !=
null; either rename the test to resolveBeforeFreezeReturnsNonNull (or similar)
to reflect its behavior, or modify the test to explicitly verify creation (e.g.,
assert absence in the registry before calling resolve and presence after) by
using the registry accessors used elsewhere in GlobalEasyGridConfiguration;
update the method name and any references accordingly.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 17eb997e-af69-427a-8309-02c50e552807

📥 Commits

Reviewing files that changed from the base of the PR and between 031a694 and 8002919.

📒 Files selected for processing (3)
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/TypedColumnDemo.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/test/EasyGridConstructionTest.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/test/GlobalEasyGridConfigurationFreezeTest.java
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/TypedColumnDemo.java

Comment on lines +55 to +59
List<String> keys = grid.getWrappedGrid().getColumns().stream()
.map(Grid.Column::getKey)
.collect(Collectors.toList());
assertThat(keys, hasItems("firstName", "lastName", "age", "birthDate", "subscriber", "active"));
}
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot May 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Tighten the auto-discovery assertion to catch unexpected columns.

hasItems(...) alone passes even if extra columns are created. Add an exact-size (or exact-content) assertion so this test fails on unintended auto-discovery changes.

Suggested patch
     List<String> keys = grid.getWrappedGrid().getColumns().stream()
         .map(Grid.Column::getKey)
         .collect(Collectors.toList());
+    assertThat(keys, hasSize(6));
     assertThat(keys, hasItems("firstName", "lastName", "age", "birthDate", "subscriber", "active"));
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
List<String> keys = grid.getWrappedGrid().getColumns().stream()
.map(Grid.Column::getKey)
.collect(Collectors.toList());
assertThat(keys, hasItems("firstName", "lastName", "age", "birthDate", "subscriber", "active"));
}
List<String> keys = grid.getWrappedGrid().getColumns().stream()
.map(Grid.Column::getKey)
.collect(Collectors.toList());
assertThat(keys, hasSize(6));
assertThat(keys, hasItems("firstName", "lastName", "age", "birthDate", "subscriber", "active"));
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@src/test/java/com/flowingcode/vaadin/addons/easygrid/test/EasyGridConstructionTest.java`
around lines 55 - 59, The test currently uses hasItems(...) which allows extra
unexpected columns; update the assertion in EasyGridConstructionTest so the
collected keys (from grid.getWrappedGrid().getColumns() -> keys) are asserted
for exact content/size — e.g., replace the hasItems assertion with an
exact-match assertion (such as assertThat(keys, contains(...)) or assertEquals
on a List of expected keys) to ensure no extra columns are present.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reviewer is wrong for two reasons.\n\n1. The test is intentionally scoped. The test name is autoDiscoveryCreatesColumnsForBeanProperties — it asserts that auto-discovery does pick up the expected properties. It makes no claim about the complete set of columns. Person has more properties than those six (e.g., phoneNumber, appointmentDateTime) that auto-discovery will also create columns for. Using contains(...) or asserting exact size would couple this test to the full property set of Person, making it break every time Person gets a new field — even if auto-discovery is working correctly.\n\n2. The complementary exact-match test already exists. explicitPropertyConstructorCreatesOnlyListedColumns uses both hasSize(2) and hasItems(...) to assert exact column membership. That is the test whose contract is "only these columns, nothing else." The division of concerns is deliberate: one test verifies auto-discovery picks up expected properties; the other verifies the explicit constructor creates exactly the specified columns.\n\nRequiring exact-match in autoDiscoveryCreatesColumnsForBeanProperties would duplicate the concern of explicitPropertyConstructorCreatesOnlyListedColumns while also making auto-discovery tests unnecessarily brittle to model changes.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reviewer is wrong for two reasons.\n\n1. The test is intentionally scoped. The test name is autoDiscoveryCreatesColumnsForBeanProperties — it asserts that auto-discovery does pick up the expected properties. It makes no claim about the complete set of columns. Person has more properties than those six (e.g., phoneNumber, appointmentDateTime) that auto-discovery will also create columns for. Using contains(...) or asserting exact size would couple this test to the full property set of Person, making it break every time Person gets a new field — even if auto-discovery is working correctly.\n\n2. The complementary exact-match test already exists. explicitPropertyConstructorCreatesOnlyListedColumns uses both hasSize(2) and hasItems(...) to assert exact column membership. That is the test whose contract is "only these columns, nothing else." The division of concerns is deliberate: one test verifies auto-discovery picks up expected properties; the other verifies the explicit constructor creates exactly the specified columns.\n\nRequiring exact-match in autoDiscoveryCreatesColumnsForBeanProperties would duplicate the concern of explicitPropertyConstructorCreatesOnlyListedColumns while also making auto-discovery tests unnecessarily brittle to model changes.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@javier-godoy, you're absolutely right on both counts — I apologize for the noise. The split is clear and well-reasoned: autoDiscoveryCreatesColumnsForBeanProperties is a scoped "subset" assertion that survives Person model evolution, while explicitPropertyConstructorCreatesOnlyListedColumns carries the exact-membership contract. Adding hasSize to the auto-discovery test would couple it to the full property set and contradict its stated intent.

(\_/)

(o . o)
(> 🥕 <)


✏️ Learnings added
Learnt from: javier-godoy
Repo: FlowingCode/EasyGridAddon PR: 10
File: src/test/java/com/flowingcode/vaadin/addons/easygrid/test/EasyGridConstructionTest.java:55-59
Timestamp: 2026-05-14T14:36:17.429Z
Learning: In EasyGridConstructionTest, `autoDiscoveryCreatesColumnsForBeanProperties` intentionally uses `hasItems(...)` without an exact-size assertion. The test only verifies that auto-discovery picks up a known subset of expected properties; `Person` has additional auto-discovered properties (e.g., `phoneNumber`, `appointmentDateTime`) beyond those six. The exact-membership contract ("only these columns, nothing else") belongs to `explicitPropertyConstructorCreatesOnlyListedColumns`, which uses both `hasSize` and `hasItems`. Do not flag the auto-discovery test for lacking a size assertion — the division of concerns is deliberate to avoid coupling the test to the full `Person` property set.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.


🧠 Learnings used
Learnt from: javier-godoy
Repo: FlowingCode/EasyGridAddon PR: 10
File: src/test/java/com/flowingcode/vaadin/addons/easygrid/ColumnConfigurationDemo.java:77-79
Timestamp: 2026-05-14T11:59:45.173Z
Learning: When reviewing EasyGridAddon code that registers a formatter via `EasyColumn.setFormatter(...)` (i.e., the lambda parameter `val`), assume `val` is non-null. `ColumnConfigurationTextRenderer` guards `formatter.apply(val)` with a null check and returns `config.getNullRepresentation()` for `val == null`, so formatter lambdas registered through `setFormatter` should not be flagged as “null-unsafe” for dereferencing `val` without an explicit null check. Only flag null-safety issues if the formatter is called from a path that does not follow this guard.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@javier-godoy, you're absolutely right — I apologize for the incorrect suggestion. The two-point reasoning is sound:

  1. autoDiscoveryCreatesColumnsForBeanProperties uses hasItems deliberately because Person has additional properties beyond those six, and the test's contract is only "these properties are discovered," not "only these properties exist."
  2. The exact-membership contract is already covered by explicitPropertyConstructorCreatesOnlyListedColumns with hasSize + hasItems, making an exact assertion here redundant and brittleness-inducing.

The division of concerns is well-designed.

(ᵔ.ᵔ) ~ noted


✏️ Learnings added
Learnt from: javier-godoy
Repo: FlowingCode/EasyGridAddon PR: 10
File: src/test/java/com/flowingcode/vaadin/addons/easygrid/test/EasyGridConstructionTest.java:55-59
Timestamp: 2026-05-14T14:36:24.110Z
Learning: In `EasyGridConstructionTest` (`src/test/java/com/flowingcode/vaadin/addons/easygrid/test/EasyGridConstructionTest.java`), the test `autoDiscoveryCreatesColumnsForBeanProperties` intentionally uses `hasItems(...)` without an exact-size assertion because `Person` has more properties than those asserted (e.g., `phoneNumber`, `appointmentDateTime` also get auto-discovered columns). The test only verifies that the expected subset of properties is discovered. The exact-membership contract ("only these columns, nothing else") is handled by the separate test `explicitPropertyConstructorCreatesOnlyListedColumns`, which uses both `hasSize` and `hasItems`. Do not flag `autoDiscoveryCreatesColumnsForBeanProperties` for lacking an exact-size assertion — that is intentional by design.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.


🧠 Learnings used
Learnt from: javier-godoy
Repo: FlowingCode/EasyGridAddon PR: 10
File: src/test/java/com/flowingcode/vaadin/addons/easygrid/ColumnConfigurationDemo.java:77-79
Timestamp: 2026-05-14T11:59:45.173Z
Learning: When reviewing EasyGridAddon code that registers a formatter via `EasyColumn.setFormatter(...)` (i.e., the lambda parameter `val`), assume `val` is non-null. `ColumnConfigurationTextRenderer` guards `formatter.apply(val)` with a null check and returns `config.getNullRepresentation()` for `val == null`, so formatter lambdas registered through `setFormatter` should not be flagged as “null-unsafe” for dereferencing `val` without an explicit null check. Only flag null-safety issues if the formatter is called from a path that does not follow this guard.

@paodb
Copy link
Copy Markdown
Member

paodb commented May 14, 2026

@coderabbitai full review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 14, 2026

✅ Actions performed

Full review triggered.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

♻️ Duplicate comments (1)
src/test/java/com/flowingcode/vaadin/addons/easygrid/service/PersonService.java (1)

30-31: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Validate pagination inputs before skip/limit.

offset < 0 or limit < 0 will fail at runtime. Guard and clamp bounds before slicing.

Suggested fix
   public List<Person> fetch(int offset, int limit) {
-    return personData.getPersons().stream().skip(offset).limit(limit).toList();
+    if (offset < 0 || limit < 0) {
+      throw new IllegalArgumentException("offset and limit must be non-negative");
+    }
+    List<Person> persons = personData.getPersons();
+    int size = persons.size();
+    if (offset >= size || limit == 0) {
+      return List.of();
+    }
+    int end = (int) Math.min((long) size, (long) offset + limit);
+    return persons.subList(offset, end);
   }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@src/test/java/com/flowingcode/vaadin/addons/easygrid/service/PersonService.java`
around lines 30 - 31, The fetch method may throw for negative pagination values;
in PersonService.fetch validate and clamp offset/limit before slicing the list
from personData.getPersons(): compute safeOffset = max(0, offset) and safeLimit
= max(0, limit), get the list size, return empty list if safeOffset >= size,
otherwise call stream().skip(safeOffset).limit(min(safeLimit, size -
safeOffset)).toList() so skip/limit never receive negative or out-of-range
values.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@src/main/java/com/flowingcode/vaadin/addons/easygrid/config/GlobalEasyGridConfiguration.java`:
- Around line 104-106: resolve(...) returns the actual mutable
ColumnConfiguration instance when frozen, so callers can still mutate global
state; change resolve to return a defensive copy or an immutable/read-only view
when frozen (e.g., if frozen return a copy or an unmodifiable wrapper of
map.get(type) instead of the live instance). Locate the resolve method and
replace the frozen branch to return a safe copy (or wrap via a new
ReadOnlyColumnConfiguration(map.get(type)) or map.get(type).copy() / clone()),
ensuring nulls are handled the same as forType(type).

In
`@src/test/java/com/flowingcode/vaadin/addons/easygrid/test/EasyColumnTestHelper.java`:
- Around line 45-46: The mocked renderer factory ignores its input and always
renders item.toString(); update the Mockito stub for mock.getRendererFactory()
in EasyColumnTestHelper to use the provided getter parameter: return a
TextRenderer that calls getter.apply(item) (or getter.apply(item)::toString as
appropriate) so the renderer uses the actual value-provider passed into the
factory instead of Object::toString; keep using
com.vaadin.flow.data.renderer.TextRenderer and ensure the lambda references the
factory parameter named getter.

In `@src/test/resources/META-INF/frontend/styles/shared-styles.css`:
- Around line 1-20: The CSS comment blocks in shared-styles.css violate the
comment-whitespace-inside rule; fix by ensuring all block comments use a single
space after the opening /* and a single space before the closing */, e.g. change
/*- and /*Demo styles*/ to /* - ... */ and /* Demo styles */ (apply consistently
across the header license block and any short comments) so stylelint passes.

---

Duplicate comments:
In
`@src/test/java/com/flowingcode/vaadin/addons/easygrid/service/PersonService.java`:
- Around line 30-31: The fetch method may throw for negative pagination values;
in PersonService.fetch validate and clamp offset/limit before slicing the list
from personData.getPersons(): compute safeOffset = max(0, offset) and safeLimit
= max(0, limit), get the list size, return empty list if safeOffset >= size,
otherwise call stream().skip(safeOffset).limit(min(safeLimit, size -
safeOffset)).toList() so skip/limit never receive negative or out-of-range
values.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 25cf5000-9af9-424b-8b60-6f55ca439bbe

📥 Commits

Reviewing files that changed from the base of the PR and between f30af8c and 23b26a3.

📒 Files selected for processing (58)
  • .gitignore
  • CONFIGURATION_RESOLUTION.md
  • FEATURE_ROW_ACTIONS.md
  • README.md
  • SPECIFICATIONS.md
  • pom.xml
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/BeanPropertyDefinition.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/EasyColumn.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/EasyGrid.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/EasyGridComposite.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/EasyGridWrapper.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/IEasyGridColumn.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/IEasyGridComposite.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/RuntimeReflectiveOperationException.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/config/ColumnConfiguration.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/config/ColumnConfigurationImpl.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/config/ColumnConfigurationLink.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/config/ColumnConfigurationTextRenderer.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/config/EasyGridConfigurationClassMap.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/config/GlobalEasyGridConfiguration.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/config/InstanceEasyGridConfiguration.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/renderers/LocalDateRenderers.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/renderers/LocalDateTimeRenderers.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/renderers/LocalTimeRenderers.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/renderers/NumberRenderers.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/renderers/RendererFactory.java
  • src/test/java/com/flowingcode/vaadin/addons/DemoLayout.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/AutoColumnsDemo.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/ColumnConfigurationDemo.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/ConfigurationHierarchyDemo.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/DemoView.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/EasyGridDemo.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/EasyGridDemoView.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/GridColumnMethodLister.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/NumberRenderingDemo.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/SelectiveColumnsDemo.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/TypeRenderingDemo.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/TypedColumnDemo.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/data/PersonData.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/it/AbstractViewTest.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/it/ViewIT.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/model/Address.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/model/NumberSample.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/model/Person.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/service/PersonService.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/test/ColumnConfigurationImplParentDelegationTest.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/test/ColumnConfigurationLinkDelegationTest.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/test/DelegationTest.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/test/EasyColumnTestHelper.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/test/EasyColumnToConfigurationDelegationTest.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/test/EasyColumnToGridColumnDelegationTest.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/test/EasyGridConstructionTest.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/test/GlobalEasyGridConfigurationFreezeTest.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/test/GlobalEasyGridConfigurationTest.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/test/GlobalRendererFactoryTest.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/test/SerializationTest.java
  • src/test/resources/META-INF/frontend/styles/easy-grid-demo-styles.css
  • src/test/resources/META-INF/frontend/styles/shared-styles.css
💤 Files with no reviewable changes (2)
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/it/ViewIT.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/EasyGridDemo.java

Comment on lines +104 to +106
public <V> ColumnConfiguration<V> resolve(Class<V> type) {
return frozen ? map.get(type) : forType(type);
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

resolve() currently allows post-freeze global mutation.

After freeze(), callers can still do GlobalEasyGridConfiguration.resolve(type).set..., which mutates global config and bypasses the “locked after startup” contract.

🔧 Minimal fix
-  public <V> ColumnConfiguration<V> resolve(Class<V> type) {
+  static <V> ColumnConfiguration<V> resolve(Class<V> type) {
     return frozen ? map.get(type) : forType(type);
   }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
public <V> ColumnConfiguration<V> resolve(Class<V> type) {
return frozen ? map.get(type) : forType(type);
}
static <V> ColumnConfiguration<V> resolve(Class<V> type) {
return frozen ? map.get(type) : forType(type);
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@src/main/java/com/flowingcode/vaadin/addons/easygrid/config/GlobalEasyGridConfiguration.java`
around lines 104 - 106, resolve(...) returns the actual mutable
ColumnConfiguration instance when frozen, so callers can still mutate global
state; change resolve to return a defensive copy or an immutable/read-only view
when frozen (e.g., if frozen return a copy or an unmodifiable wrapper of
map.get(type) instead of the live instance). Locate the resolve method and
replace the frozen branch to return a safe copy (or wrap via a new
ReadOnlyColumnConfiguration(map.get(type)) or map.get(type).copy() / clone()),
ensuring nulls are handled the same as forType(type).

Comment thread src/test/resources/META-INF/frontend/styles/shared-styles.css Outdated
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@CONFIGURATION_RESOLUTION.md`:
- Around line 31-33: Update the docs to use the canonical API name: replace
examples calling easyGrid.configuration.forType(...) with the spec-defined
easyGrid.typeConfiguration(Class) usage; ensure all occurrences (including the
other example block currently showing easyGrid.configuration.forType) are
changed so the docs consistently reference easyGrid.typeConfiguration and its
Class-based signature.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: cd8a906a-8d1b-4d18-b379-b191c49380a3

📥 Commits

Reviewing files that changed from the base of the PR and between 8002919 and 0691f32.

📒 Files selected for processing (58)
  • .gitignore
  • CONFIGURATION_RESOLUTION.md
  • FEATURE_ROW_ACTIONS.md
  • README.md
  • SPECIFICATIONS.md
  • pom.xml
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/BeanPropertyDefinition.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/EasyColumn.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/EasyGrid.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/EasyGridComposite.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/EasyGridWrapper.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/IEasyGridColumn.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/IEasyGridComposite.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/RuntimeReflectiveOperationException.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/config/ColumnConfiguration.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/config/ColumnConfigurationImpl.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/config/ColumnConfigurationLink.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/config/ColumnConfigurationTextRenderer.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/config/EasyGridConfigurationClassMap.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/config/GlobalEasyGridConfiguration.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/config/InstanceEasyGridConfiguration.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/renderers/LocalDateRenderers.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/renderers/LocalDateTimeRenderers.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/renderers/LocalTimeRenderers.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/renderers/NumberRenderers.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/renderers/RendererFactory.java
  • src/test/java/com/flowingcode/vaadin/addons/DemoLayout.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/AutoColumnsDemo.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/ColumnConfigurationDemo.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/ConfigurationHierarchyDemo.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/DemoView.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/EasyGridDemo.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/EasyGridDemoView.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/GridColumnMethodLister.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/NumberRenderingDemo.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/SelectiveColumnsDemo.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/TypeRenderingDemo.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/TypedColumnDemo.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/data/PersonData.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/it/AbstractViewTest.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/it/ViewIT.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/model/Address.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/model/NumberSample.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/model/Person.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/service/PersonService.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/test/ColumnConfigurationImplParentDelegationTest.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/test/ColumnConfigurationLinkDelegationTest.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/test/DelegationTest.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/test/EasyColumnTestHelper.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/test/EasyColumnToConfigurationDelegationTest.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/test/EasyColumnToGridColumnDelegationTest.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/test/EasyGridConstructionTest.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/test/GlobalEasyGridConfigurationFreezeTest.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/test/GlobalEasyGridConfigurationTest.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/test/GlobalRendererFactoryTest.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/test/SerializationTest.java
  • src/test/resources/META-INF/frontend/styles/easy-grid-demo-styles.css
  • src/test/resources/META-INF/frontend/styles/shared-styles.css
💤 Files with no reviewable changes (3)
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/EasyGridDemo.java
  • src/test/resources/META-INF/frontend/styles/shared-styles.css
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/it/ViewIT.java
✅ Files skipped from review due to trivial changes (8)
  • .gitignore
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/RuntimeReflectiveOperationException.java
  • src/test/resources/META-INF/frontend/styles/easy-grid-demo-styles.css
  • README.md
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/config/InstanceEasyGridConfiguration.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/it/AbstractViewTest.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/DemoView.java
  • src/test/java/com/flowingcode/vaadin/addons/DemoLayout.java
🚧 Files skipped from review as they are similar to previous changes (44)
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/EasyGridDemoView.java
  • FEATURE_ROW_ACTIONS.md
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/model/Address.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/model/NumberSample.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/GridColumnMethodLister.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/test/GlobalEasyGridConfigurationTest.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/model/Person.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/config/EasyGridConfigurationClassMap.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/renderers/LocalDateTimeRenderers.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/config/ColumnConfigurationTextRenderer.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/renderers/RendererFactory.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/test/EasyColumnToGridColumnDelegationTest.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/NumberRenderingDemo.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/test/GlobalEasyGridConfigurationFreezeTest.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/EasyGrid.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/test/EasyGridConstructionTest.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/TypedColumnDemo.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/test/SerializationTest.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/SelectiveColumnsDemo.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/config/ColumnConfigurationLink.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/config/ColumnConfiguration.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/renderers/NumberRenderers.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/ConfigurationHierarchyDemo.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/IEasyGridColumn.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/test/EasyColumnTestHelper.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/service/PersonService.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/renderers/LocalDateRenderers.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/TypeRenderingDemo.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/test/GlobalRendererFactoryTest.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/EasyGridComposite.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/data/PersonData.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/config/ColumnConfigurationImpl.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/EasyGridWrapper.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/BeanPropertyDefinition.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/EasyColumn.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/test/EasyColumnToConfigurationDelegationTest.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/renderers/LocalTimeRenderers.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/test/ColumnConfigurationImplParentDelegationTest.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/test/ColumnConfigurationLinkDelegationTest.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/config/GlobalEasyGridConfiguration.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/ColumnConfigurationDemo.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/IEasyGridComposite.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/test/DelegationTest.java
  • pom.xml

Comment on lines +31 to +33
```java
easyGrid.configuration.forType(Entity.class).setTextAlign(RIGHT);
```
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Use the same instance-configuration API name as the spec (typeConfiguration).

These examples use easyGrid.configuration.forType(...), but the spec defines instance type config via easyGrid.typeConfiguration(Class). Keeping one canonical API name avoids ambiguity in generated usage guidance.

Suggested doc fix
- easyGrid.configuration.forType(Entity.class).setTextAlign(RIGHT);
+ easyGrid.typeConfiguration(Entity.class).setTextAlign(RIGHT);

- easyGrid.configuration.forType(Entity.class).setFormatter(e -> e.getId().toString());
+ easyGrid.typeConfiguration(Entity.class).setFormatter(e -> e.getId().toString());

Also applies to: 50-52

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@CONFIGURATION_RESOLUTION.md` around lines 31 - 33, Update the docs to use the
canonical API name: replace examples calling easyGrid.configuration.forType(...)
with the spec-defined easyGrid.typeConfiguration(Class) usage; ensure all
occurrences (including the other example block currently showing
easyGrid.configuration.forType) are changed so the docs consistently reference
easyGrid.typeConfiguration and its Class-based signature.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: To Do

Development

Successfully merging this pull request may close these issues.

2 participants